package com.macro.mall.common.log.aspect;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 打印请求参数
 * @Author: alan
 * @Date: 2019/6/27 4:25 PM
 */

@Order(2)
@Slf4j
@Aspect
@Component
public class MapperAspect {
    /**
     * 以 controller 包下定义的所有请求为切入点
     */
    @Pointcut("execution(public * com.macro.mall.dao..*.*(..))")
    public void webLog() {
    }

    /**
     * 在切点之前织入
     *
     * @param proceedingJoinPoint
     * @throws Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        TimeInterval timer = DateUtil.timer();
        // 开始打印请求日志

        Object result = proceedingJoinPoint.proceed();
        // 构建成一条长 日志，避免并发下日志错乱
        StringBuilder beforeReqLog = new StringBuilder(1000);

        // 日志参数
        List<Object> beforeReqArgs = new ArrayList<>();
        getLogArgs(beforeReqLog, beforeReqArgs, proceedingJoinPoint.getSignature(),
                proceedingJoinPoint.getArgs());


        // 执行耗时
        beforeReqLog.append("mapper耗时 : {} ms\n");
        beforeReqArgs.add(timer.interval());
        beforeReqLog.append(
                "============= End ==========\n");
        log.info(beforeReqLog.toString(), beforeReqArgs.toArray());
        return result;
    }


    @AfterThrowing(pointcut = "webLog()", throwing = "e")
    public void doAfterThrow(JoinPoint joinPoint, Exception e) {

    }


    private void getLogArgs( StringBuilder beforeReqLog, List<Object> beforeReqArgs,
                            Signature signature, Object[] args) {
        // 打印请求相关参数
        beforeReqLog.append("\n");
        beforeReqLog.append(
                "========= Start ===========\n");

        // 打印调用 controller 的全路径以及执行方法
        beforeReqLog.append("Class Method   : {}.{}\n");
        beforeReqArgs.add(signature.getDeclaringTypeName());
        beforeReqArgs.add(signature.getName());
        // 打印请求入参
        List<Object> objects = new ArrayList<>();
        for (Object arg : args) {
            boolean isResponse = (arg instanceof HttpServletResponse);
            boolean isRequest = (arg instanceof HttpServletRequest);
            if (!isRequest && !isResponse) {
                objects.add(arg);
            }
        }
        if (!objects.isEmpty()) {
            beforeReqLog.append("Request Args   : {}\n");
            beforeReqArgs.add(JSONUtil.toJsonStr(objects));
        }
    }


}
